package ch.poole.openinghoursfragment.pickers;

import ch.poole.openinghoursfragment.ResourceTable;
import ch.poole.openinghoursfragment.pickers.dialogpicker.DialogPickerView;
import ch.poole.openinghoursfragment.pickers.dialogpicker.NumberPickerView;
import ch.poole.openinghoursparser.DateWithOffset;
import ch.poole.openinghoursparser.Month;
import ch.poole.openinghoursparser.VarDate;
import ch.poole.openinghoursparser.YearRange;
import com.lxj.xpopup.impl.ConfirmPopupView;
import com.lxj.xpopup.interfaces.OnConfirmListener;
import com.ryan.ohos.extension.event.interfaces.View;
import ohos.agp.components.Component;
import ohos.agp.utils.TextTool;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;

/**
 * Display a dialog allowing the user to select values for a start date and optionally an end date
 */
public class DateRangePicker {
    private static final int MAX_YEAR = 2100;

    public static final int NOTHING_SELECTED = Integer.MIN_VALUE;

    private static final String TITLE = "title";
    private static final String START_YEAR = "startYear";
    private static final String START_MONTH = "startMonth";
    private static final String START_DAY = "startDay";
    private static final String START_VARDATE = "startVarDate";
    private static final String START_ONLY = "startOnly";
    private static final String END_YEAR = "endYear";
    private static final String END_MONTH = "endMonth";
    private static final String END_DAY = "endDay";
    private static final String END_VARDATE = "endVarDate";

    private static final String TAG = "fragment_daterangepicker";
    private static ConfirmPopupView popupView;
    private static String[] yearValues;
    private static String[] monthEntries;
    private static String[] varDateEntries;
    private static String[] dayValues;
    private static NumberPickerView npvStartYear;
    private static NumberPickerView npvStartMonth;
    private static NumberPickerView npvStartDay;
    private static NumberPickerView npvEndYear;
    private static NumberPickerView npvEndMonth;
    private static NumberPickerView npvEndDay;
    private static SetDateRangeListener listener;
    private static NumberPickerView npvEndVarDate;
    private static NumberPickerView npvStartVarDate;


    private static void initDialogView(boolean startOnly, int startYear, Month startMonth, int startDay, VarDate startVarDate, int endYear,
                                       @Nullable Month endMonth, int endDay, VarDate endVarDate) {

        npvStartYear = (NumberPickerView) popupView.findComponentById(ResourceTable.Id_start_year);
        npvStartYear.setDisplayedData(yearValues);
        npvStartYear.setMinValue(0);
        npvStartYear.setMaxValue(yearValues.length - 1);
        npvStartYear.setValue(startYear != YearRange.UNDEFINED_YEAR ? getYearValue(startYear) : 0);

        npvStartMonth = (NumberPickerView) popupView.findComponentById(ResourceTable.Id_start_month);
        npvStartDay = (NumberPickerView) popupView.findComponentById(ResourceTable.Id_start_day);
        npvStartMonth.setVisibility(Component.VISIBLE);
        npvStartDay.setVisibility(Component.VISIBLE);

        npvStartVarDate = (NumberPickerView) popupView.findComponentById(ResourceTable.Id_startVarDate);
        npvStartVarDate.setMinValue(0);
        npvStartVarDate.setMaxValue(1);
        npvStartVarDate.setDisplayedData(varDateEntries);
        npvStartVarDate.setValue(0);

        npvStartMonth.setDisplayedData(monthEntries);
        npvStartMonth.setMinValue(0);
        npvStartMonth.setMaxValue(11);
        if (startMonth != null) {
            npvStartMonth.setValue(startMonth.ordinal());
        } else {
            npvStartMonth.setValue(0);
        }

        npvStartDay.setDisplayedData(dayValues);
        npvStartDay.setMinValue(0);
        npvStartDay.setMaxValue(31);
        npvStartDay.setValue(startDay != DateWithOffset.UNDEFINED_MONTH_DAY ? startDay : 0);

        npvEndYear = (NumberPickerView) popupView.findComponentById(ResourceTable.Id_end_year);
        npvEndYear.setDisplayedData(yearValues);
        npvEndYear.setMinValue(0);
        npvEndYear.setMaxValue(yearValues.length - 1);
        npvEndYear.setValue(endYear != YearRange.UNDEFINED_YEAR ? getYearValue(endYear) : 0);

        npvEndMonth = (NumberPickerView) popupView.findComponentById(ResourceTable.Id_end_month);
        npvEndDay = (NumberPickerView) popupView.findComponentById(ResourceTable.Id_end_day);


        npvEndVarDate = (NumberPickerView) popupView.findComponentById(ResourceTable.Id_endVarDate);
        npvEndVarDate.setMinValue(0);
        npvEndVarDate.setMaxValue(1);
        npvEndVarDate.setDisplayedData(varDateEntries);
        npvEndVarDate.setValue(0);


        if (startVarDate == null) {
            npvStartVarDate.setVisibility(Component.HIDE);
            npvStartMonth.setVisibility(Component.VISIBLE);
            npvStartDay.setVisibility(Component.VISIBLE);
        } else {
            npvStartVarDate.setVisibility(Component.VISIBLE);
            npvStartMonth.setVisibility(Component.HIDE);
            npvStartDay.setVisibility(Component.HIDE);
        }

        if (startOnly) {
            npvEndYear.setVisibility(Component.HIDE);
            npvEndVarDate.setVisibility(Component.HIDE);
            npvEndMonth.setVisibility(Component.HIDE);
            npvEndDay.setVisibility(Component.HIDE);
        } else {

            if (endVarDate == null) {
                npvEndVarDate.setVisibility(Component.HIDE);
                npvEndMonth.setVisibility(Component.VISIBLE);
                npvEndDay.setVisibility(Component.VISIBLE);

                String[] tempMonthValues = new String[monthEntries.length + 1];
                tempMonthValues[0] = "-";
                for (int i = 0; i < monthEntries.length; i++) {
                    tempMonthValues[i + 1] = monthEntries[i];
                }

                npvEndMonth.setDisplayedData(tempMonthValues);
                npvEndMonth.setMinValue(0);
                npvEndMonth.setMaxValue(12);
                npvEndMonth.setValue(endMonth != null ? endMonth.ordinal() + 1 : 0);

                npvEndDay.setDisplayedData(dayValues);
                npvEndDay.setMinValue(0);
                npvEndDay.setMaxValue(31);
                npvEndDay.setValue(endDay != DateWithOffset.UNDEFINED_MONTH_DAY ? endDay : 0);
            } else {
                npvEndVarDate.setVisibility(Component.VISIBLE);
                npvEndMonth.setVisibility(Component.HIDE);
                npvEndDay.setVisibility(Component.HIDE);
            }
        }
    }


    /**
     * Show the DateRangePicker dialog
     *
     * @param context       context
     * @param title         title
     * @param startYear     startYear
     * @param startMonth    startMonth
     * @param startDay      startDay
     * @param endYear       endYear
     * @param endMonth      endMonth
     * @param endDay        endDay
     * @param rangeListener rangeListener
     * @throws IOException NotExistException
     */
    public static void showDialog(@NotNull Context context, int title, int startYear, @NotNull Month startMonth, int startDay, int endYear,
                                  @Nullable Month endMonth, int endDay, SetDateRangeListener rangeListener) {
        try {
            final String titleStr = context.getResourceManager().getElement(title).getString();
            newInstance(context, titleStr, "确定", startYear, startMonth, startDay, null, false, endYear, endMonth, endDay, null, rangeListener);
            if (popupView != null) {
                popupView.show();
            }
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
    }


    /**
     * Show the DateRangePicker dialog
     *
     * @param context       context
     * @param title         title
     * @param startYear     startYear
     * @param startVarDate  startVarDate
     * @param endYear       endYear
     * @param endMonth      endMonth
     * @param endDay        endDay
     * @param rangeListener rangeListener
     * @throws IOException        IOException
     * @throws NotExistException  NotExistException
     * @throws WrongTypeException WrongTypeException
     */
    public static void showDialog(Context context, int title, int startYear, VarDate startVarDate, int endYear, @Nullable Month endMonth,
                                  int endDay, SetDateRangeListener rangeListener) {
        try {
            final String titleStr = context.getResourceManager().getElement(title).getString();
            newInstance(context, titleStr, "确定", startYear, null, 0, startVarDate, false, endYear, endMonth,
                    endDay, null, rangeListener);
            if (popupView != null) {
                popupView.show();
            }
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
    }


    /**
     * Show the DateRangePicker dialog
     *
     * @param context       context
     * @param title         title
     * @param startYear     startYear
     * @param startMonth    startMonth
     * @param startDay      startDay
     * @param endYear       endYear
     * @param endVarDate    endVarDate
     * @param rangeListener rangeListener
     * @throws IOException        IOException
     * @throws NotExistException  NotExistException
     * @throws WrongTypeException WrongTypeException
     */
    public static void showDialog(Context context, int title, int startYear, @NotNull Month startMonth, int startDay, int endYear,
                                  VarDate endVarDate, SetDateRangeListener rangeListener) {
        try {
            final String titleStr = context.getResourceManager().getElement(title).getString();
            newInstance(context, titleStr, "确定", startYear, startMonth, startDay, null, false, endYear, null, 0, endVarDate, rangeListener);
            if (popupView != null) {
                popupView.show();
            }
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
    }

    /**
     * Show the DateRangePicker dialog
     *
     * @param context       context
     * @param title         title
     * @param startYear     startYear
     * @param startMonth    startMonth
     * @param startDay      startDay
     * @param rangeListener rangeListener
     * @throws IOException        IOException
     * @throws NotExistException  NotExistException
     * @throws WrongTypeException WrongTypeException
     */
    public static void showDialog(Context context, int title, int startYear, @NotNull Month startMonth, int startDay, SetDateRangeListener rangeListener) {
        try {
            final String titleStr = context.getResourceManager().getElement(title).getString();
            newInstance(context, titleStr, "确定", startYear, startMonth, startDay, null, true, 0, null, 0, null, rangeListener);
            if (popupView != null) {
                popupView.show();
            }
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
    }


    /**
     * Show the DateRangePicker dialog
     *
     * @param context       context
     * @param title         title
     * @param startYear     startYear
     * @param startVarDate  startVarDate
     * @param rangeListener rangeListener
     * @throws IOException        IOException
     * @throws NotExistException  NotExistException
     * @throws WrongTypeException WrongTypeException
     */
    public static void showDialog(Context context, int title, int startYear, VarDate startVarDate, SetDateRangeListener rangeListener) {
        try {
            final String titleStr = context.getResourceManager().getElement(title).getString();
            newInstance(context, titleStr, "确定", startYear, null, 0, startVarDate, true, 0, null, 0, null, rangeListener);
            if (popupView != null) {
                popupView.show();
            }
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
    }


    /**
     * Show the DateRangePicker dialog
     *
     * @param context       context
     * @param title         title
     * @param startYear     startYear
     * @param startVarDate  startVarDate
     * @param endYear       endYear
     * @param endVarDate    endVarDate
     * @param rangeListener rangeListener
     * @throws IOException        IOException
     * @throws NotExistException  NotExistException
     * @throws WrongTypeException WrongTypeException
     */
    public static void showDialog(Context context, int title, int startYear, VarDate startVarDate, int endYear, VarDate endVarDate, SetDateRangeListener rangeListener) {
        try {
            final String titleStr = context.getResourceManager().getElement(title).getString();
            newInstance(context, titleStr, "确定", startYear, null, 0, startVarDate, false, endYear, null, 0, endVarDate, rangeListener);
            if (popupView != null) {
                popupView.show();
            }
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
    }

    /**
     * Create a new instance of DateRangePicker
     *
     * @param context       context
     * @param tit           resource id for the title to display
     * @param sureText      sureText
     * @param startYear     initial start year
     * @param startMonth    initial start month or null
     * @param startDay      initial start day of the month
     * @param startVarDate  startVarDate
     * @param startOnly     only show a picker for one date
     * @param endYear       initial end year
     * @param endMonth      initial end month or null
     * @param endDay        initial end day of the month
     * @param endVarDate    endVarDate
     * @param rangeListener rangeListener
     * @return an instance of DateRangePicker
     * @throws IOException        IOException
     * @throws NotExistException  NotExistException
     * @throws WrongTypeException WrongTypeException
     */

    public static DateRangePicker newInstance(Context context, String tit, String sureText, int startYear,
                                              @Nullable Month startMonth, int startDay, VarDate startVarDate,
                                              boolean startOnly, int endYear, @Nullable Month endMonth, int endDay, VarDate endVarDate, SetDateRangeListener rangeListener) {
        DateRangePicker f = new DateRangePicker();
        listener = rangeListener;
        String title = TextTool.isNullOrEmpty(tit) ? "Picker" : tit;
        yearValues = new String[MAX_YEAR - YearRange.FIRST_VALID_YEAR + 2];
        yearValues[0] = "-";
        for (int i = YearRange.FIRST_VALID_YEAR; i <= MAX_YEAR; i++) {
            yearValues[i - YearRange.FIRST_VALID_YEAR + 1] = Integer.toString(i);
        }

        try {
            monthEntries = context.getResourceManager().getElement(ResourceTable.Strarray_months_entries).getStringArray();
            varDateEntries = context.getResourceManager().getElement(ResourceTable.Strarray_vardate_entries).getStringArray();
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }

        dayValues = new String[32];
        dayValues[0] = "-";
        for (int i = 1; i <= 31; i++) {
            dayValues[i] = Integer.toString(i);
        }

        popupView = DialogPickerView.getInstance(context, title, sureText, ResourceTable.Layout_dialog_date_range_picker, new OnConfirmListener() {

            @Override
            public void onConfirm() {
                int startYearValue = getYearValue(npvStartYear);
                Month startMonthValue = getMonthValue(npvStartMonth);
                int startDayValue = getDayValue(npvStartDay);
                int endYearValue = getYearValue(npvEndYear);
                Month endMonthValue = getEndMonthValue(npvEndMonth);
                int endDayValue = getDayValue(npvEndDay);
                VarDate startVarDateValue;
                if (npvStartVarDate.getVisibility() == Component.VISIBLE) {
                    startVarDateValue = VarDate.getValue("easter");
                } else {
                    startVarDateValue = null;
                }
                VarDate endVarDateValue;
                if (npvEndVarDate.getVisibility() == Component.VISIBLE) {
                    endVarDateValue = VarDate.getValue("easter");
                } else {
                    endVarDateValue = null;
                }

                listener.setDateRange(startYearValue, startMonthValue, null,
                        startDayValue, startVarDateValue, endYearValue, endMonthValue, null, endDayValue, endVarDateValue);
            }

            private Month getMonthValue(final NumberPickerView npvMonth) {
                Month monthValue = Month.values()[0];
                if (npvMonth.getValue() != 0) {
                    monthValue = Month.values()[npvMonth.getValue()];
                }
                return monthValue;
            }
            private Month getEndMonthValue(final NumberPickerView npvMonth) {
                Month monthValue = Month.values()[0];
                if (npvMonth.getValue() != 0) {
                    monthValue = Month.values()[npvMonth.getValue()-1];
                }
                return monthValue;
            }

            private int getYearValue(final NumberPickerView npvYear) {
                int yearValue = npvYear.getValue();
                int returnValue;
                if (yearValue == 0) {
                    returnValue = NOTHING_SELECTED;
                } else {
                    returnValue = yearValue + YearRange.FIRST_VALID_YEAR - 1;
                }
                return returnValue;
            }

            private int getDayValue(final NumberPickerView npvEndDay) {
                int dayValue = npvEndDay.getValue();
                if (dayValue == 0) {
                    dayValue = NOTHING_SELECTED;
                }
                return dayValue;
            }

            private VarDate getVarDateValue(final NumberPickerView npvVarDate) {
                VarDate varDateValue = null;
                if (npvVarDate.getValue() != 0) {
                    varDateValue = VarDate.values()[npvVarDate.getValue() - 1];
                }
                return varDateValue;
            }
        }, null).build();
        initDialogView(startOnly, startYear, startMonth, startDay, startVarDate, endYear,
                endMonth, endDay, endVarDate);


        return f;
    }

    private static int getYearValue(int year) {
        int Value = 0;
        if (yearValues == null || yearValues.length == 0) {
            Value = 0;
        } else {
            for (int i = 0; i < yearValues.length; i++) {
                if (yearValues[i].equals("" + year)) {
                    Value = i;
                    break;
                }
            }
        }
        return Value;
    }

}
